﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml.Serialization;
using System.Collections.Specialized;

namespace ShootSearch.FileSystem
{
    /// <summary>
    /// Header :4 byte header length
    /// 
    /// </summary>
    public class FileObject : IFileObject
    {
        protected Encoding encoding = Encoding.UTF8;

        #region Constructors
        public FileObject()
        {
            DateTime = System.DateTime.Now;
        }

        public FileObject(string url, string page)
        {
            DateTime = System.DateTime.Now;
            this.Url = url;
            ContentType = "text/html";
            Encoding = Encoding.UTF8;
            Content = Encoding.GetBytes(page);
        }

        public FileObject(string url, string contentType, byte[] content)
        {
            DateTime = System.DateTime.Now;
            this.Url = url;
            Encoding = Encoding.UTF8;
            ContentType = contentType;
            Content = content;
        } 
        #endregion

        #region IFileObject Members

        public bool Deleted { get; set; }
        public DateTime DateTime { get; set; }
        public Encoding Encoding
        {
            get { return encoding; }
            set
            {
                if (value != null) encoding = value;
            }
        }
        public string Url { get; set; }
        public string ContentType { get; set; }
        public byte[] Content { get; set; }

        

        public byte[] ToBytes()
        {
            MemoryStream ms = new MemoryStream();
            BinaryWriter bw = new BinaryWriter(ms);

            byte[] buff = ToOriginalBytes();
            bw.Write(buff.Length);
            bw.Write(buff);

            ms.Seek(0, SeekOrigin.Begin);
            buff = new byte[ms.Length];
            ms.Read(buff, 0, buff.Length);

            bw.Close();
            ms.Close();


            return buff;
        }

        public void FromBytes(byte[] bytes)
        {
            MemoryStream ms = new MemoryStream(bytes);
            Read(ms);
            ms.Close();
        }

        public void Read(Stream stream)
        {
            byte[] buff = new byte[4];
            stream.Read(buff, 0, buff.Length);
            int length = BitConverter.ToInt32(buff, 0);

            if (length > 0)
            {
                //Read the whole fileobject
                buff = new byte[length];
                stream.Read(buff, 0, buff.Length);
                //Parse the header and the content
                BinaryReader memReader = new BinaryReader(new MemoryStream(buff));
                ReadHeader(memReader);
                int contentLength = memReader.ReadInt32();
                if (contentLength > 0)
                {
                    Content = memReader.ReadBytes(contentLength);
                }
                memReader.Close();
            }
        }

        public void Write(Stream stream)
        {
            byte[] buff = ToOriginalBytes();
            byte[] buffLenth = BitConverter.GetBytes(buff.Length);
            //Write the whole fileobject length
            stream.Write(buffLenth, 0, buffLenth.Length);
            //Write the content
            stream.Write(buff, 0, buff.Length);

        }
        
        #endregion

        #region Protected Methods
        protected byte[] ToOriginalBytes()
        {
            MemoryStream ms = new MemoryStream();
            BinaryWriter bw = new BinaryWriter(ms);
            WriteHeader(bw);

            //Content [int] or [int bytes]
            if (Content == null)
            {
                bw.Write(0);
            }
            else
            {
                bw.Write(Content.Length);
                bw.Write(Content);
            }

            ms.Seek(0, SeekOrigin.Begin);
            byte[] buff = new byte[ms.Length];
            ms.Read(buff, 0, buff.Length);
            bw.Close();
            ms.Close();
            return buff;
        }
        
        protected void WriteHeader(BinaryWriter bwriter)
        {
            //Write Deleted  [bit]
            bwriter.Write(Deleted);
            //DateTime [long]
            bwriter.Write(DateTime.Ticks);
            //CodePage [int]
            bwriter.Write(Encoding.CodePage);

            //Write url [int bytes]
            byte[] urlBytes = Encoding.GetBytes(Url);
            bwriter.Write(urlBytes.Length);
            bwriter.Write(urlBytes);

            //Write content type [int bytes]
            byte[] contentBytes = Encoding.GetBytes(ContentType);
            bwriter.Write(contentBytes.Length);
            bwriter.Write(contentBytes);
        }

        protected void ReadHeader(BinaryReader breader)
        {
            //Deleted  [bit]
            Deleted = breader.ReadBoolean();
            //DateTime [long]
            DateTime = new DateTime(breader.ReadInt64());
            //CodePage [int]
            Encoding = Encoding.GetEncoding(breader.ReadInt32());

            //Read url [int bytes]
            int length = breader.ReadInt32();
            byte[] buff = breader.ReadBytes(length);
            Url = Encoding.GetString(buff);

            //Read content type [int bytes]
            length = breader.ReadInt32();
            buff = breader.ReadBytes(length);
            ContentType = Encoding.GetString(buff);

        }

        #endregion
    } 
       



}
